home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 May / macformat-024.iso / Shareware City / Developers / nshellmegasource1.50 / mega src / commands / cat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-30  |  7.5 KB  |  354 lines  |  [TEXT/KAHL]

  1. /* ========== the commmand file: ==========
  2.  
  3.     cat.c
  4.     
  5.     Copyright (c) 1993,1994 Newport Software Development
  6.     
  7.     You may distribute unmodified copies of this file for
  8.     noncommercial purposes.  You may use this file as a
  9.     reference when writing your own nShell(tm) commands.
  10.     
  11.     All other rights are reserved.
  12.     
  13.    ========== the commmand file: ========== */
  14.  
  15. #define    CAT_BUF_SIZE    2048
  16.  
  17. #ifdef __MWERKS__            // CodeWarrior requires an A4 setup
  18. #include <A4Stuff.h>
  19. #endif
  20.  
  21. #include <script.h>
  22. #include <string.h>
  23.  
  24. #include "nshc.h"
  25.  
  26. #include "arg_utl.proto.h"
  27. #include "fss_utl.proto.h"
  28. #include "fss_utl2.proto.h"
  29. #include "nshc_utl.proto.h"
  30. #include "str_utl.proto.h"
  31.  
  32. // data definition - this struct is the root of all data
  33.  
  34. typedef enum { copy_none, copy_data, copy_rsrc } c_state;
  35.  
  36. typedef struct {
  37.  
  38.     int        by_file;        // 1 if files are listed, 0 if stdin
  39.  
  40.     int        got_fss;        // 0 if FSSpec calls are not available
  41.  
  42.     int        arg;            // position in arg list
  43.     
  44.     short    fref;            // file ref. number, 0 if no file open
  45.  
  46. } t_cat_data;
  47.  
  48. typedef    t_cat_data    **CDataH;
  49.  
  50. /* ======================================== */
  51.  
  52. // prototypes - utility
  53.  
  54. void cat_bad( t_nshc_parms *nshc_parms, int code );
  55. void cat_bad_file( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, StringPtr msg );
  56. void cat_good( t_nshc_parms *nshc_parms );
  57.  
  58. // prototypes - file copy routines
  59.  
  60. void cat_open( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, t_cat_data **hData );
  61. void cat_read_write( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, t_cat_data **hData );
  62.  
  63. // prototypes - console copy routines
  64.  
  65. void cat_console( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls );
  66.  
  67. // prototypes - state machine
  68.  
  69. void cat_start( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls  );
  70. void cat_continue( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls );
  71. void cat_stop( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls );
  72.  
  73. /* ======================================== */
  74.  
  75. // utility routines
  76.  
  77. /* ======================================== */
  78.  
  79. void cat_bad(  t_nshc_parms *nshc_parms, int code )
  80. {
  81.     nshc_parms->action = nsh_stop;
  82.     nshc_parms->result = code;
  83. }
  84.  
  85. void cat_bad_file(  t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, StringPtr msg )
  86. {
  87.     nshc_calls->NSH_putStr_err("\pcat: File access error (");
  88.     nshc_calls->NSH_putStr_err(msg);
  89.     nshc_calls->NSH_putStr_err("\p)\r");
  90.  
  91.     nshc_parms->action = nsh_stop;
  92.     nshc_parms->result = NSHC_ERR_GENERAL;
  93. }
  94.  
  95. void cat_good(  t_nshc_parms *nshc_parms )
  96. {
  97.     nshc_parms->action = nsh_stop;
  98.     nshc_parms->result = 0;
  99. }
  100.  
  101. /* ======================================== */
  102.  
  103. // file access routines
  104.  
  105. /* ======================================== */
  106.  
  107. void cat_open( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, t_cat_data **hData )
  108. {
  109.     int        result;
  110.     long    dirID;
  111.     Boolean    isDir;
  112.     FSSpec    fss;
  113.     
  114.     (**hData).fref = 0;
  115.  
  116.     // =====> convert path to fsspec
  117.     
  118.     result = arg_to_fss( nshc_parms, nshc_calls, (**hData).arg, &fss );
  119.  
  120.     (**hData).arg++;
  121.     
  122.     if (result) {
  123.         cat_bad( nshc_parms, result );
  124.         return;
  125.         }
  126.     
  127.     result = fss_to_DirID( &fss, &dirID, &isDir );
  128.         
  129.     if (( result == noErr) && isDir) {
  130.         nshc_calls->NSH_putStr_err("\pcat: Skiping directory = ");
  131.         nshc_calls->NSH_putStr_err((StringPtr)fss.name);
  132.         nshc_calls->NSH_putchar('\r');
  133.         return;
  134.         }
  135.             
  136.     if ( result == fnfErr ) {
  137.         nshc_calls->NSH_putStr_err("\pcat: File not found = ");
  138.         nshc_calls->NSH_putStr_err((StringPtr)fss.name);
  139.         nshc_calls->NSH_putchar('\r');
  140.         return;
  141.         }
  142.             
  143.     if (!result)
  144.         result = fss_OpenDF((**hData).got_fss, &fss, fsRdPerm, &(**hData).fref);
  145.     
  146.     if ( result ) {
  147.         cat_bad_file( nshc_parms, nshc_calls, (StringPtr)fss.name );
  148.         return;
  149.         }
  150. }
  151.  
  152. /* ======================================== */
  153.  
  154. void cat_read_write( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, t_cat_data **hData )
  155. {
  156.     int        close;
  157.     int        temp;
  158.     int        result;
  159.     long    bcount;
  160.     char    buf[CAT_BUF_SIZE+1];
  161.     
  162.     result = close = 0;
  163.     
  164.     // =====> copy the data fork
  165.     
  166.     bcount = CAT_BUF_SIZE;
  167.     result = FSRead( (**hData).fref, &bcount, &buf );
  168.     
  169.     if (( result == noErr ) || ( result == eofErr )) {
  170.     
  171.         if (result == eofErr) {
  172.             close = 1;
  173.             result = 0;
  174.             }
  175.         
  176.         if (bcount) {
  177.             buf[bcount] = '\0';
  178.             nshc_calls->NSH_puts( buf );
  179.             }
  180.         
  181.         }
  182.     else
  183.         cat_bad_file( nshc_parms, nshc_calls, "\pread data" );
  184.     
  185.     // =====> close the input file
  186.     
  187.     if (close) {
  188.  
  189.         if ( (**hData).fref ) {
  190.             if ( temp = FSClose( (**hData).fref ) )
  191.                 result = temp;
  192.             (**hData).fref = 0;
  193.             }
  194.             
  195.         if (result)
  196.             cat_bad_file( nshc_parms, nshc_calls, "\pclose file" );
  197.                 
  198.         }
  199. }
  200.  
  201. /* ======================================== */
  202.  
  203. // console access routines
  204.  
  205. /* ======================================== */
  206.  
  207. #define    LINES_PER_PASS    10
  208.  
  209. void cat_console( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls )
  210. {
  211.     long    bcount;
  212.     char    buf[LINE_MAX];
  213.     char    c;
  214.     int        i;
  215.     int        temp;
  216.     int        pass;
  217.     
  218.     // if characters are waiting, pick up a few lines
  219.         
  220.     pass = 1;
  221.     
  222.     while ( pass++ < LINES_PER_PASS ) {
  223.     
  224.         bcount = nshc_calls->NSH_gets( buf, LINE_MAX );
  225.         
  226.         if (!bcount) return;            // go get more characters
  227.         
  228.         nshc_calls->NSH_puts( buf );    // display the line
  229.         
  230.         if ( bcount == -1 )     {            // end of input, set-up for exit
  231.             cat_good( nshc_parms );
  232.             return;
  233.             }
  234.             
  235.         }
  236. }
  237.  
  238. /* ======================================== */
  239.  
  240. // state machine - core routines
  241.  
  242. /* ======================================== */
  243.  
  244. void cat_start( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls  )
  245. {
  246.     CDataH    hData;    // handle to hold our data
  247.     
  248.     nshc_parms->action = nsh_continue;
  249.  
  250.     hData = (CDataH)NewHandleClear(sizeof(t_cat_data));
  251.     
  252.     if (hData) {
  253.         (**hData).by_file = nshc_parms->argc > 1;    // if we have args, do file i/o
  254.         (**hData).arg = 1;                            // start at the arg = 1 position
  255.         (**hData).got_fss = fss_test();                // test if we can use FSSpec calls
  256.         nshc_parms->data = (Handle)hData;
  257.         }
  258.     else {
  259.         nshc_calls->NSH_putStr_err( "\pcat: Could not allocate storage.\r" );
  260.         cat_bad( nshc_parms, NSHC_ERR_MEMORY );
  261.         }
  262. }
  263.  
  264. /* ======================================== */
  265.  
  266. void cat_continue( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls )
  267. {
  268.     CDataH    hData;
  269.  
  270.     if (hData = (CDataH)nshc_parms->data) {
  271.  
  272.         if ( (**hData).by_file ) {
  273.         
  274.             // if we are not in the middle of a file, open one
  275.  
  276.             if ( !(**hData).fref )
  277.                 cat_open( nshc_parms, nshc_calls, hData );
  278.  
  279.             // read and write some of the open file
  280.  
  281.             if ( (**hData).fref )
  282.                 cat_read_write( nshc_parms, nshc_calls, hData );
  283.  
  284.             // and see if we are done
  285.  
  286.             if ( !(**hData).fref && ( (**hData).arg >= nshc_parms->argc ) )
  287.                 cat_good( nshc_parms );
  288.                 
  289.             }
  290.         else
  291.             cat_console( nshc_parms, nshc_calls );
  292.  
  293.         }
  294. }
  295.  
  296. /* ======================================== */
  297.  
  298. void cat_stop( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls )
  299. {
  300.     short    fRef;
  301.     CDataH    hData;
  302.     int        temp;
  303.     int        result;
  304.     
  305.     result = 0;
  306.     
  307.     if (hData = (CDataH)nshc_parms->data) {
  308.     
  309.         if ( (**hData).fref ) {
  310.             if ( temp = FSClose( (**hData).fref ) )
  311.                 result = temp;
  312.             (**hData).fref = 0;
  313.             }
  314.             
  315.         DisposeHandle(nshc_parms->data);
  316.         }
  317.         
  318.     if (result)
  319.         cat_bad_file( nshc_parms, nshc_calls, "\pclosing files" );
  320.         
  321.     nshc_parms->action = nsh_idle;
  322. }
  323.  
  324. /* ======================================== */
  325.  
  326. void main(t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls)
  327. {
  328. #ifdef __MWERKS__
  329.     long oldA4  = SetCurrentA4();
  330. #endif
  331.     
  332.     if ( !nshc_bad_version( nshc_parms, nshc_calls, NSHC_VERSION ) ) {
  333.     
  334.         switch (nshc_parms->action) {
  335.             case nsh_start:
  336.                 cat_start(nshc_parms, nshc_calls);
  337.                 break;
  338.             case nsh_continue:
  339.                 cat_continue(nshc_parms, nshc_calls);
  340.                 break;
  341.             case nsh_stop:
  342.                 cat_stop(nshc_parms, nshc_calls);
  343.                 break;
  344.             }
  345.         
  346.         }
  347.  
  348. #ifdef __MWERKS__
  349.     SetA4(oldA4);
  350. #endif
  351. }
  352.  
  353. /* ======================================== */
  354.